package cn.net.autocode.platform.menus;

import cn.net.autocode.core.bean.ResultT;
import cn.net.autocode.core.utils.TreeUtils;
import cn.net.autocode.core.utils.UserThreadLocalUtils;
import cn.net.autocode.dbManager.Dao;
import cn.net.autocode.dbManager.IdWorker;
import cn.net.autocode.platform.cache.AutoCacheUtil;
import cn.net.autocode.platform.function.service.FuncServ;
import cn.net.autocode.platform.menus.service.MenuServ;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/platform/menus")
public class PlatformMenusCtrl {

    private final Dao dao;

    private final FuncServ funcServ;

    private final MenuServ menuServ;

    private final  AutoCacheUtil cacheUtil;

    public PlatformMenusCtrl(Dao dao, FuncServ funcServ, MenuServ menuServ, AutoCacheUtil cacheUtil) {
        this.dao = dao;
        this.funcServ = funcServ;
        this.menuServ = menuServ;
        this.cacheUtil = cacheUtil;
    }

    @RequestMapping("menuTree")
    public ResultT menuTree(@RequestBody JSONObject param){
        JSONArray array = dao.queryJSONArray("select * from sys_menus order by menu_type,sort_no");
        JSONArray treeArray = TreeUtils.commonTree(array);
        return ResultT.success(treeArray);
    }

    @RequestMapping("save")
    public ResultT save(@RequestBody JSONObject menu){
        String id = menu.getString("id");
        if(id == null || id.isBlank()){
            String parentId = menu.getString("parentId");
            if (parentId == null || parentId.isBlank()) {
                parentId = "-1";
                menu.put("parentId", parentId);
                menu.put("menuType", "0");
            }else{
                String menuType = dao.queryValue("select menu_type from sys_menus where id=?",String.class, parentId);
                if ("0".equals(menuType)) {
                    menu.put("menuType", "1");
                }else if ("1".equals(menuType)) {
                    menu.put("menuType", "2");
                }else{
                    return ResultT.fail("PC端菜单最大支持三级，不能再添加子菜单！");
                }
            }
            //获取最大的序号值
            int sortNo = dao.maxSort("select max(sort_no) from sys_menus where parent_id=?",parentId);
            menu.put("sortNo", sortNo);
            menu.put("id", IdWorker.ulid());
            dao.createJSON(menu,"sys_menus");
        }else{
            dao.updateJSON(menu,"sys_menus");
        }
        return ResultT.success(menu);
    }

    @RequestMapping("saveApp")
    public ResultT saveApp(@RequestBody JSONObject menu){
        int sortNo=dao.queryValue("select count(*) from sys_menus where parent_id=?", Integer.class,menu.getString("parentId"));
        dao.executeUpdate("update sys_menus set parent_id=?,sort_no=? where id=?",menu.getString("parentId"),sortNo,menu.getString("id"));
        return ResultT.success();
    }

    @RequestMapping("move")
    @Transactional
    public ResultT move(@RequestBody JSONObject menu){
        String parentId = menu.getString("parentId");
        String id = menu.getString("id");

        JSONObject parentMenu = dao.queryJSON("select * from sys_menus where id=?",parentId);
        String parentMenuType = parentMenu.getString("menuType");
        String menuType;
        if(parentMenuType==null || parentMenuType.isBlank()){
            menuType = "0";
        }else if(parentMenuType.equals("0")){
            menuType = "1";
        }else if(parentMenuType.equals("1")){
            menuType = "2";
        }else{
            return ResultT.fail("系统最多支持三级菜单，不能进行转移！");
        }

        int sortNo=dao.queryValue("select count(*) from sys_menus where parent_id=?", Integer.class,parentId);
        dao.executeUpdate("update sys_menus set parent_id=?,sort_no=?,menu_type=? where id=?",parentId,sortNo,menuType,id);
        JSONObject rs = new JSONObject();
        rs.put("menuType",menuType);
        return ResultT.success(rs);
    }

    @RequestMapping("moveApp")
    public ResultT moveApp(@RequestBody JSONObject menu){
        int sortNo=dao.queryValue("select count(*) from app_menus where parent_id=?", Integer.class,menu.getString("parentId"));
        dao.executeUpdate("update app_menus set parent_id=?,sort_no=? where id=?",menu.getString("parentId"),sortNo,menu.getString("id"));
        return ResultT.success();
    }

    @RequestMapping("sort")
    public ResultT sort(@RequestBody JSONObject menu){
        JSONArray ids = menu.getJSONArray("ids");
        String parentId=menu.getString("parentId");
        int size = ids.size();
        for(int i=0;i<size;i++){
            dao.executeUpdate("update sys_menus set parent_id=?,sort_no=? where id=?",parentId,i,ids.getString(i));
        }
        return ResultT.success();
    }

    @RequestMapping("sortApp")
    public ResultT sortApp(@RequestBody JSONObject menu){
        JSONArray ids = menu.getJSONArray("ids");
        String parentId=menu.getString("parentId");
        int size = ids.size();
        for(int i=0;i<size;i++){
            dao.executeUpdate("update app_menus set parent_id=?,sort_no=? where id=?",parentId,i,ids.getString(i));
        }
        return ResultT.success();
    }

    @RequestMapping("del")
    @Transactional
    public ResultT del(@RequestBody JSONObject menu){
        String id = menu.getString("id");

        int num = dao.queryValue("select count(*) from sys_menus where parent_id=?", Integer.class,id);
        if(num>0){
            return ResultT.fail("存在子菜单，不允许进行删除！");
        }
        dao.executeUpdate("delete from sys_organ_menu where menu_id=?",id);
        dao.executeUpdate("delete from sys_role_menus where menu_id=?",id);
        dao.executeUpdate("delete from sys_menus where id=?",id);

        return ResultT.success();
    }

    @RequestMapping("delApp")
    @Transactional
    public ResultT delApp(@RequestBody JSONObject menu){
        String id = menu.getString("id");
        int num = dao.queryValue("select count(*) from app_menus where parent_id=?", Integer.class,id);
        if(num>0){
            return ResultT.fail("存在子菜单，不允许进行删除！");
        }
        dao.executeUpdate("delete from app_organ_menu where menu_id=?",id);
        dao.executeUpdate("delete from app_role_menus where menu_id=?",id);
        dao.executeUpdate("delete from app_menus where id=?",id);
        return ResultT.success();
    }

    @RequestMapping("queryCalc")
    public ResultT queryCalc(@RequestBody JSONObject param){
        JSONObject json=dao.queryJSON("select id,menu_type,calc_name from sys_menus where id=?", param.getString("id"));
        if(json.isEmpty()){
            return ResultT.fail("没有对应的菜单");
        }

        if(json.getString("menuType").equals("0")){
            return ResultT.fail("一级菜单不能设置计算文本");
        }
        json.put("content",json.getString("calcName"));

        return ResultT.success(json);
    }

    @RequestMapping("queryAppCalc")
    public ResultT queryAppCalc(@RequestBody JSONObject param){
        JSONObject json=dao.queryJSON("select id,menu_type,calc_name from app_menus where id=?", param.getString("id"));
        if(json.isEmpty()){
            return ResultT.fail("没有对应的菜单");
        }

        if(json.getString("menuType").equals("0")){
            return ResultT.fail("一级菜单不能设置计算文本");
        }
        json.put("content",json.getString("calcName"));

        return ResultT.success(json);
    }

    @RequestMapping("saveCalc")
    public ResultT saveCalc(@RequestBody JSONObject param){
        dao.executeUpdate("update sys_menus set calc_name=? where id=?",param.getString("content"),param.getString("id"));
        return ResultT.success();
    }

    @RequestMapping("saveAppCalc")
    public ResultT saveAppCalc(@RequestBody JSONObject param){
        dao.executeUpdate("update app_menus set calc_name=? where id=?",param.getString("content"),param.getString("id"));
        return ResultT.success();
    }

    @RequestMapping("queryParam")
    public ResultT queryParam(@RequestBody JSONObject param){
        JSONObject json=dao.queryJSON("select id,menu_param content,menu_type from sys_menus where sys_menus.id=?", param.getString("id"));
        if(json.isEmpty()){
            return ResultT.fail("没有对应的菜单");
        }

        if(json.getString("menuType").equals("0")){
            return ResultT.fail("一级菜单不能设置请求参数");
        }
        return ResultT.success(json);
    }

    @RequestMapping("saveParam")
    public ResultT saveParam(@RequestBody JSONObject param){
        dao.executeUpdate("update sys_menus set menu_param=? where id=?",param.getString("content"),param.getString("id"));
        return ResultT.success();
    }

    @RequestMapping("queryFunctions")
    public ResultT queryFunctions(){
        return ResultT.success(funcServ.queryPageTree(true));
    }

    /**
     * 获取用户菜单
     *
     * @return 菜单列表
     */
    @PostMapping(value = "userMenus", produces = "application/json;charset=UTF-8")
    public ResultT userMenus() {
        String orgCode = UserThreadLocalUtils.getOrgCode();
        String userName = UserThreadLocalUtils.getUserName();

        //获取可以访问的菜单Id
        List<String> menuIds = new ArrayList<>();
        //获取系统菜单
        String systemUser = dao.queryValue("select system_user from autocode_platform",String.class);
        if (userName.equalsIgnoreCase(systemUser)) {
            List<String> systemMenus = dao.queryListValue("select id from sys_menus where is_system='Y'",String.class);
            menuIds.addAll(systemMenus);
        }

        //获取管理员菜单
        String orgManager = dao.queryValue("select org_manager from sys_organ where code=?",String.class,orgCode);
        if (userName.equalsIgnoreCase(orgManager)) {
            List<String> managerMenus = dao.queryListValue("select id from sys_menus t1 where t1.is_manager='Y' and (exists(select 1 from sys_organ_menu t2 where t1.id=t2.menu_id and t2.org_code=?) or t1.is_public='Y')",String.class,orgCode);
            menuIds.addAll(managerMenus);
        }

        //获取角色菜单
        List<String> roleMenus = dao.queryListValue("select t1.menu_id from sys_role_users t0,sys_role_menus t1,sys_organ_menu t2 where t0.org_code=? and t0.username=? and t0.role_id=t1.role_id and t1.menu_id=t2.menu_id and t0.org_code=t2.org_code", String.class,orgCode,userName);
        menuIds.addAll(roleMenus);

        //获取父级菜单
        if (!menuIds.isEmpty()){
            String parentSql = "select distinct parent_id from sys_menus where id in (?)  or id in (select parent_id from sys_menus t2 where t2.id in (?))";
            List<String> parentIds = dao.queryListValue(parentSql,String.class,menuIds,menuIds);
            menuIds.addAll(parentIds);
        }

        //获取菜单信息
        JSONArray menus = new JSONArray();
        if (!menuIds.isEmpty()) {
            menus = dao.queryJSONArray("select * from sys_menus where id in (?)  order by menu_type,sort_no ",menuIds);
        }

        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            String showName = menu.getString("showName");
            if (showName!=null && !showName.isBlank()) {
                menu.put("name",showName);
            }
        }

        menuServ.menuDeal(menus,"N");
        JSONArray menusTree = TreeUtils.commonTree(menus);
        return ResultT.success(menusTree);
    }

    /**
     * 获取用户菜单
     *
     * @return 菜单列表
     */
    @PostMapping(value = "mobileMenusTree", produces = "application/json;charset=UTF-8")
    public ResultT mobileMenusTree() {
        String orgCode = UserThreadLocalUtils.getOrgCode();
        String userName = UserThreadLocalUtils.getUserName();

        //获取角色菜单，获取可以访问的菜单Id
        List<String> menuIds = dao.queryListValue("select t1.menu_id from sys_role_users t0,app_role_menus t1,app_organ_menu t2 where t0.org_code=? and t0.username=? and t0.role_id=t1.role_id and t1.menu_id=t2.menu_id and t0.org_code=t2.org_code", String.class,orgCode,userName);

        if (!menuIds.isEmpty()){
            String parentSql = "select distinct parent_id from app_menus where id in (?)  or id in (select parent_id from app_menus t2 where t2.id in (?))";
            List<String> parentIds = dao.queryListValue(parentSql,String.class,menuIds,menuIds);
            menuIds.addAll(parentIds);
        }

        //获取菜单信息
        JSONArray menus = new JSONArray();
        if (!menuIds.isEmpty()) {
            menus = dao.queryJSONArray("select * from app_menus where id in (?) order by menu_type,sort_no ",menuIds);
        }
        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            String showName = menu.getString("showName");
            if (showName!=null && !showName.isBlank()) {
                menu.put("name",showName);
            }
        }

        //处理菜单
        menuServ.menuDeal(menus,"Y");
        JSONArray menusTree = TreeUtils.commonTree(menus);

        //只保留子菜单不为空的选项
        JSONArray orgMenus = new JSONArray();
        for(int i=0;i<menusTree.size();i++){
            JSONObject parentMenu = menusTree.getJSONObject(i);
            JSONArray childMenus = parentMenu.getJSONArray("children");
            if (childMenus!=null && !childMenus.isEmpty()){
                orgMenus.add(parentMenu);
            }
        }
        return ResultT.success(orgMenus);
    }

    /**
     * 获取用户菜单
     * @return 菜单列表
     */
    @PostMapping(value = "mobileMenus", produces = "application/json;charset=UTF-8")
    public ResultT mobileMenus() {
        String orgCode = UserThreadLocalUtils.getOrgCode();
        String userName = UserThreadLocalUtils.getUserName();

        //获取角色菜单，获取可以访问的菜单Id
        List<String> menuIds = dao.queryListValue("select t1.menu_id from sys_role_users t0,app_role_menus t1,app_organ_menu t2 where t0.org_code=? and t0.username=? and t0.role_id=t1.role_id and t1.menu_id=t2.menu_id and t0.org_code=t2.org_code", String.class,orgCode,userName);


        //获取菜单信息
        JSONArray menus = new JSONArray();
        if (!menuIds.isEmpty()) {
            menus = dao.queryJSONArray("select * from app_menus where id in (?)  or id in (select parent_id from app_menus t2 where t2.id in (?))  order by menu_type,sort_no ",menuIds,menuIds);
        }
        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            String showName = menu.getString("showName");
            if (showName!=null && !showName.isBlank()) {
                menu.put("name",showName);
            }
        }

        //处理菜单
        menuServ.menuDeal(menus,"Y");
        JSONArray menusTree = TreeUtils.commonTree(menus);

        JSONArray orgMenus = new JSONArray();
        for(int i=0;i<menusTree.size();i++){
            JSONObject parentMenu = menusTree.getJSONObject(i);
            JSONArray childMenus = parentMenu.getJSONArray("children");
            if (childMenus!=null && !childMenus.isEmpty()){
                orgMenus.addAll(childMenus);
            }
        }
        return ResultT.success(orgMenus);
    }


    /**
     * 获取用户菜单
     *
     * @return 菜单列表
     */
    @PostMapping(value = "userMenusCounter", produces = "application/json;charset=UTF-8")
    public ResultT userMenusCounter() {
        JSONObject user = cacheUtil.getTokenUser(UserThreadLocalUtils.getToken(),"N");
        JSONObject counterMenus = user.getJSONObject("counterMenus");

        List<String> annotationList = new ArrayList<>();
        for(Map.Entry<String,Object> entry:counterMenus.entrySet()){
            annotationList.add(entry.getValue().toString());
        }

        //获取需要计算的菜单
        JSONObject menuCounters = new JSONObject();
        Map<String,Integer> menuCountMap = menuServ.menuCounter(annotationList);
        for(Map.Entry<String,Object> entry:counterMenus.entrySet()){
            menuCounters.put(entry.getKey(), menuCountMap.getOrDefault(entry.getValue().toString(), -1));
        }
        return ResultT.success(menuCounters);
    }

    /**
     * 获取用户菜单
     *
     * @return 菜单列表
     */
    @PostMapping(value = "saveOrganMenus", produces = "application/json;charset=UTF-8")
    @ResponseBody
    @Transactional
    public ResultT saveOrganMenus(@RequestBody JSONObject param) {
        String orgCode = param.getString("orgCode");
        JSONArray checkedKeys = param.getJSONArray("checkedKeys");

        //删除最顶层的菜单
        String sql1 = "select distinct parent_id from sys_menus";
        List<String> parentIds = dao.queryListValue(sql1,String.class);

        List<String> leafMenus = new ArrayList<>();
        for(int i=0;i<checkedKeys.size();i++){
            String menuId = checkedKeys.getString(i);
            if(!parentIds.contains(menuId)){
                leafMenus.add(menuId);
            }
        }

        //删除不存在的menuId
        if (!leafMenus.isEmpty()) {
            dao.executeUpdate("delete from sys_organ_menu where org_code=? and menu_id not in (?)",orgCode,leafMenus);
        }else{
            dao.executeUpdate("delete from sys_organ_menu where org_code=?",orgCode);
        }

        //删除角色中不存在的menuId
        if (!leafMenus.isEmpty()) {
            dao.executeUpdate("delete from sys_role_menus t1 where exists(select 1 from sys_roles t2 where t2.is_public='N' and t2.org_code=? and t1.role_id=t2.id) and t1.menu_id not in (?)",orgCode,leafMenus);
        }else{
            dao.executeUpdate("delete from sys_role_menus t1 where exists(select 1 from sys_roles t2 where t2.is_public='N' and t2.org_code=? and t1.role_id=t2.id)",orgCode);
        }

        //插入新的菜单id
        List<String> existsMenus = dao.queryListValue("select menu_id from sys_organ_menu where org_code=?",String.class,orgCode);
        leafMenus.removeAll(existsMenus);
        for(String menuId:leafMenus){
            dao.executeUpdate("insert into sys_organ_menu(id,org_code,menu_id) values(?,?,?)", IdWorker.ulid(),orgCode,menuId);
        }
        return ResultT.success();
    }

    /**
     * 获取用户菜单
     *
     * @return 菜单列表
     */
    @PostMapping(value = "saveAppOrganMenus", produces = "application/json;charset=UTF-8")
    @ResponseBody
    @Transactional
    public ResultT saveAppOrganMenus(@RequestBody JSONObject param) {
        String orgCode = param.getString("orgCode");
        JSONArray checkedKeys = param.getJSONArray("checkedKeys");

        //删除最顶层的菜单
        String sql1 = "select distinct parent_id from app_menus";
        List<String> parentIds = dao.queryListValue(sql1,String.class);

        List<String> leafMenus = new ArrayList<>();
        for(int i=0;i<checkedKeys.size();i++){
            String menuId = checkedKeys.getString(i);
            if(!parentIds.contains(menuId)){
                leafMenus.add(menuId);
            }
        }

        //删除不存在的menuId
        if (!leafMenus.isEmpty()) {
            dao.executeUpdate("delete from app_organ_menu where org_code=? and menu_id not in (?)",orgCode,leafMenus);
        }else{
            dao.executeUpdate("delete from app_organ_menu where org_code=?",orgCode);
        }

        //删除角色中不存在的menuId
        if (!leafMenus.isEmpty()) {
            dao.executeUpdate("delete from app_role_menus t1 where exists(select 1 from sys_roles t2 where t2.is_public='N' and t2.org_code=? and t1.role_id=t2.id) and t1.menu_id not in (?)",orgCode,leafMenus);
        }else{
            dao.executeUpdate("delete from app_role_menus t1 where exists(select 1 from sys_roles t2 where t2.is_public='N' and t2.org_code=? and t1.role_id=t2.id)",orgCode);
        }

        //插入新的菜单id
        List<String> existsMenus = dao.queryListValue("select menu_id from app_organ_menu where org_code=?",String.class,orgCode);
        leafMenus.removeAll(existsMenus);
        for(String menuId:leafMenus){
            dao.executeUpdate("insert into app_organ_menu(id,org_code,menu_id) values(?,?,?)", IdWorker.ulid(),orgCode,menuId);
        }
        return ResultT.success();
    }

    /**
     * 获取用户菜单
     *
     * @return 菜单列表
     */
    @PostMapping(value = "organMenus", produces = "application/json;charset=UTF-8")
    @ResponseBody
    @Transactional
    public ResultT organMenus(@RequestBody JSONObject param) {
        JSONArray organMenus = menuServ.organMenus(true);
        return ResultT.success(organMenus);
    }

}
